import string
from array import array
from Glitch import Glitch


nexus_doFastNextTok = False

nexus_punctuation = '\(\)\[\]\{\}\\\/\,\;\:\=\*\'\"\`\+\-\<\>'  # no period, '!', #, @, _, &, ^, %, $
phylip_punctuation = '\(\)\,\;\:'
punctuation = nexus_punctuation

def _del_nothing(self):
    gm = ["Don't/Can't delete this property."]
    raise Glitch, gm

_nexus_getLineEndingsAsTokens = array('l',[0])

def _set_nexus_getLineEndingsAsTokens(self, newVal):
    try:
        newVal = int(newVal)
        self._nexus_getLineEndingsAsTokens[0] = newVal
    except:
        gm = ['This property should be set to an int.']
        raise Glitch, gm

nexus_getLineEndingsAsTokens = property(lambda self: self._nexus_getLineEndingsAsTokens[0],
                                          _set_nexus_getLineEndingsAsTokens, _del_nothing)


_nexus_writeVisibleComments = array('l',[0])

def _set_nexus_writeVisibleComments(self, newVal):
    try:
        newVal = int(newVal)
        self._nexus_writeVisibleComments[0] = newVal
    except:
        gm = ['This property should be set to an int.']
        raise Glitch, gm

nexus_writeVisibleComments = property(lambda self: self._nexus_writeVisibleComments[0],
                                          _set_nexus_writeVisibleComments, _del_nothing)

_nexus_getAllCommandComments = array('l',[0]) 

def _set_nexus_getAllCommandComments(self, newVal):
    try:
        newVal = int(newVal)
        self._nexus_getAllCommandComments[0] = newVal
    except:
        gm = ['This property should be set to an int.']
        raise Glitch, gm

nexus_getAllCommandComments = property(lambda self: self._nexus_getAllCommandComments[0],
                                          _set_nexus_getAllCommandComments, _del_nothing)

_nexus_getWeightCommandComments = array('l',[1])

def _set_nexus_getWeightCommandComments(self, newVal):
    try:
        newVal = int(newVal)
        self._nexus_getWeightCommandComments[0] = newVal
    except:
        gm = ['This property should be set to an int.']
        raise Glitch, gm

nexus_getWeightCommandComments = property(lambda self: self._nexus_getWeightCommandComments[0],
                                          _set_nexus_getWeightCommandComments, _del_nothing)


_nexus_getP4CommandComments = array('l',[0]) 

def _set_nexus_getP4CommandComments(self, newVal):
    try:
        newVal = int(newVal)
        self._nexus_getP4CommandComments[0] = newVal
    except:
        gm = ['This property should be set to an int.']
        raise Glitch, gm

nexus_getP4CommandComments = property(lambda self: self._nexus_getP4CommandComments[0],
                                          _set_nexus_getP4CommandComments, _del_nothing)




def sortListOfObjectsOnAttribute(aListOfObjects, attributeString):
    #
    def pairing(anObject, a=attributeString):
        return (getattr(anObject, a), anObject)
    paired = map(pairing, aListOfObjects)
    #print paired
    # 'paired' is a list of 2-element tuples, (thingToSortOn, theOriginalObject)
    paired.sort()
    def stripit(pair):
        return pair[1]
    return map(stripit, paired)


def nexusUnquoteName(theName):
    """Deal with quotes.  Returns theName

    If theName is not quoted, just return it.  If
    theName is quoted, remove the outside quotes, and convert any
    cases of 2 single quotes in a row to 1 single quote."""

    if theName[0] == '\'':
        if theName[-1] != "'":
            gm = ['func.nexusUnquotName()']
            gm.append('the name is %s' % theName)
            gm.append("First char is a single quote, but last char is not.")
            raise Glitch, gm
        theName = theName[1:-1]
        if theName.count('\'\''):
            return theName.replace('\'\'', '\'')
        else:
            return theName
    else:
        return theName

def nexusFixNameIfQuotesAreNeeded(theName, verbose=0):
    """Add quotes if needed, for writing to a Nexus file.

    Returns a possibly modified theName.  Usually it will not need
    quoting, so it just returns theName unchanged.

    If theName is None, or if it starts with a single quote, just return it.

    If it has (nexus-defined) punctuation, or spaces, then put quotes
    around it before returning it.  If there are internal single
    quotes, then double them, nexus-style.  Except if there are any
    already doubled single quotes, don't double them.  """

    if theName == None:
        return theName
    if theName.startswith('\''):
        return theName
    quotesAreNeeded = 0
    #for c in var.nexus_punctuation:
    for c in punctuation:
        if c in theName:
            quotesAreNeeded = 1
            break
    if not quotesAreNeeded:
        for c in string.whitespace:
            if c in theName:
                quotesAreNeeded = 1
                break
    if quotesAreNeeded:
        if verbose:
            oldName = theName
        if theName.count('\''):
            # If we have doubled quotes, don't re-double them
            if theName.count('\'\''):
                pass
            else:
                theName = theName.replace('\'', '\'\'')
        newName = '\'' + theName + '\''
        if verbose:
            print "Warning. Nexus quoting |%s| to |%s|" % (oldName, newName)
        return newName
    else:
        return theName
    
       


def nexusCheckName(theName):
        """Check to see if theName conforms to Nexus standards."""
        if type(theName) != type('string'):
            return 0
        if 0:
            return 1
        if len(theName) == 1 and theName[0] not in string.letters:
            return 0
        try:
            int(theName)
            return 0 # we don't allow all-digit names
        except ValueError:
            return 1
    

